﻿cmake_minimum_required(VERSION 3.10)

include(config.cmake OPTIONAL)

#----------------------- 环境参数 ----------------------
set(PROJECT_ROOT ${CMAKE_CURRENT_LIST_DIR}/..)
file(RELATIVE_PATH PROJECT_ROOT_NAME ${PROJECT_ROOT}/.. ${PROJECT_ROOT})

if("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Windows")
	set(USERNAME $ENV{USERNAME})
else()
	set(USERNAME $ENV{USER})
endif()

#----------------------- 取默认参数宏 ----------------------
macro(set_default)
if("${${ARGV0}}" STREQUAL "")
	set(${ARGV0} $ENV{${ARGV0}})	
	if("${${ARGV0}}" STREQUAL "")	    
		set(${ARGV0} ${ARGV1} ${ARGV2} ${ARGV3} ${ARGV4} ${ARGV5} ${ARGV6})
	endif()
endif()
endmacro()

#----------------------- 配置参数 ----------------------
set_default(PROJECT_NAME ${PROJECT_ROOT_NAME})
set_default(APP_NAME ${PROJECT_NAME})
set_default(ACTIVITY_NAME android.app.NativeActivity)
set_default(MAJOR_VERSION 1)
set_default(MINOR_VERSION 0)
set_default(REVISION 0)
set_default(BUILD_NUMBER 1)
set_default(PACKAGE_NAME com.${USERNAME}.${PROJECT_NAME})
set_default(VERSION_CODE ${BUILD_NUMBER})
set_default(VERSION_NAME ${MAJOR_VERSION}.${MINOR_VERSION}.${REVISION}.${BUILD_NUMBER})
set_default(MIN_SDK_VERSION 28)
set_default(DEBUG_ABI arm64-v8a)
set_default(KEYSTORE_PASSWORD 12345678)
set_default(CMAKE_BUILD_TYPE Release)

set_default(SOURCE_GLOB ../src/*.c ../src/*.cpp *.c *.cpp) #源码
set_default(HEADER_GLOB ../src/*.h ../include/*.h *.h) #头文件
set_default(EXCLUDES CMakeFiles) #排除文件
set_default(LIBS log android EGL) #链接库
set_default(CFLAGS -Wall ) #编译选项
set_default(LDFLAGS -Wall ) #链接选项

#----------------------- 环境变量检测 ----------------------
if(NOT DEFINED ENV{JAVA_HOME})
    message(FATAL_ERROR "Must install JDK and define JAVA_HOME environment")    
endif()
if(NOT DEFINED ENV{ANDROID_NDK})
    message(FATAL_ERROR "Must install Android NDK and define ANDROID_NDK environment")    
endif()
if(NOT DEFINED ENV{ANDROID_PLATFORM})
    message(FATAL_ERROR "Must install Android Platform and define ANDROID_PLATFORM environment")    
endif()
if(NOT DEFINED ENV{ANDROID_BUILD_TOOLS})
    message(FATAL_ERROR "Must install Android Build Tools and define ANDROID_BUILD_TOOLS environment")    
endif()

#----------------------- 引入编译器 ----------------------
if(NOT EXISTS $ENV{ANDROID_NDK}/build/cmake/android.toolchain.cmake)
    message(FATAL_ERROR "File Not Found : $ENV{ANDROID_NDK}/build/cmake/android.toolchain.cmake")
endif()
if(NOT EXISTS $ENV{ANDROID_NDK}/build/cmake/abis.cmake)
    message(FATAL_ERROR "File Not Found : $ENV{ANDROID_NDK}/build/cmake/abis.cmake")
endif()
set(ANDROID_PLATFORM ${MIN_SDK_VERSION})
include($ENV{ANDROID_NDK}/build/cmake/android.toolchain.cmake) 
include($ENV{ANDROID_NDK}/build/cmake/abis.cmake) 


#----------------------- 查找所有源码文件和头文件 ----------------------
file(GLOB_RECURSE ALL_SOURCES ${SOURCE_GLOB}) 
file(GLOB_RECURSE ALL_HEADERS ${HEADER_GLOB})

#----------------------- 按EXLUDES变量过滤掉不需要编译的文件 ----------------------
set(EXCLUDES ${EXCLUDES} .*/CMakeFiles/.*) 
foreach(EXCL IN LISTS EXCLUDES) 
	list(FILTER ALL_SOURCES EXCLUDE REGEX ${EXCL})
	list(FILTER ALL_HEADERS EXCLUDE REGEX ${EXCL})
endforeach()

#----------------------- 将每个头文件所在目录添加到include ----------------------
foreach(FILENAME IN LISTS ALL_HEADERS)
	get_filename_component(DIRNAME ${FILENAME} DIRECTORY)	
	if(NOT "${DIRNAME}" IN_LIST INCS)
		list(APPEND INCS ${DIRNAME})		
	endif()
endforeach()
foreach(INC IN LISTS INCS)
	include_directories(${INC})
endforeach()
include_directories(${PROJECT_ROOT}/include)

#----------------------- 根据源码文件类型确定语言 ----------------------
set(HAS_C )
set(HAS_CXX )
foreach(FILENAME IN LISTS ALL_SOURCES)
	get_filename_component(EXTNAME ${FILENAME} EXT)	
	if(NOT ${EXTNAME} STREQUAL ".c")
		set(HAS_CXX CXX)
	else()
		set(HAS_C C)	
	endif()
endforeach()
project(${PROJECT_NAME} LANGUAGES ${HAS_C} ${HAS_CXX})



#----------------------- 其他编译参数设置 ----------------------

#导出compile_commands.json文件

set(CMAKE_CXX_FLAGS "")
set(CMAKE_C_FLAGS "")

link_libraries(${LIBS})
link_libraries(${LDFLAGS})
add_compile_options(${CFLAGS})

set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE)


if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")	
	set(DEBUGGABLE true)
else()	
	link_libraries(-s)
	set(DEBUGGABLE false)
endif()

#-------------------- 编译多ABI动态库 --------------------
if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
	set(BUILD_ABI ${DEBUG_ABI})
else()
	set(BUILD_ABI ${NDK_DEFAULT_ABIS})
endif()
foreach(ABINAME IN LISTS BUILD_ABI)
    set(TRIPLE ${NDK_ABI_${ABINAME}_LLVM_TRIPLE})
    set(OUTDIR ${CMAKE_BINARY_DIR}/jniLibs/lib/${ABINAME})
    file(MAKE_DIRECTORY "${OUTDIR}")
    set(TARGET_NAME ${PROJECT_NAME}_${ABINAME})
    if(${ABINAME} STREQUAL "armeabi-v7a")
		set(COMPILE_FLAGS "${CFLAGS} -mthumb --target=${TRIPLE}${ANDROID_PLATFORM}") 
    else()
		set(COMPILE_FLAGS "${CFLAGS} --target=${TRIPLE}${ANDROID_PLATFORM}") 
    endif()       
    add_library(${TARGET_NAME} SHARED ${ALL_SOURCES})     
    set(LINK_FLAGS "${COMPILE_FLAGS}")
    set_target_properties(${TARGET_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${OUTDIR}) 
    set_target_properties(${TARGET_NAME} PROPERTIES LIBRARY_OUTPUT_NAME ${PROJECT_NAME}) 
    set_target_properties(${TARGET_NAME} PROPERTIES COMPILE_FLAGS ${COMPILE_FLAGS})
    set_target_properties(${TARGET_NAME} PROPERTIES LINK_FLAGS ${LINK_FLAGS})	
endforeach()

#-------------------- 资源目录 --------------------
set_default(MANIFEST ${CMAKE_CURRENT_LIST_DIR}/AndroidManifest.xml)
set_default(ASSETS ${PROJECT_ROOT}/assets)
set_default(RES ${CMAKE_CURRENT_LIST_DIR}/res)

#-------------------- manifest处理 --------------------
if(NOT EXISTS ${MANIFEST})
	message("-- Configure AndroidManifest.xml.in ...")
	set(MANIFEST_IN ${CMAKE_CURRENT_LIST_DIR}/AndroidManifest.xml.in)
	set(MANIFEST ${CMAKE_BINARY_DIR}/AndroidManifest.xml)
	configure_file("${MANIFEST_IN}" "${MANIFEST}")
endif()
set(APK_DEPS ${MANIFEST})

#-------------------- res处理 --------------------
if(EXISTS ${CMAKE_CURRENT_LIST_DIR}/values/strings.xml.in)
	message("-- Configure strings.xml.in ...")
	file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/res/values")
	set(STRINGS_XML_IN ${CMAKE_CURRENT_LIST_DIR}/values/strings.xml.in)
	set(STRINGS_XML ${CMAKE_BINARY_DIR}/res/values/strings.xml)
	configure_file("${STRINGS_XML_IN}" "${STRINGS_XML}")
	set(RES_STRING -S ${CMAKE_BINARY_DIR}/res)
	set(APK_DEPS ${APK_DEPS} ${STRINGS_XML})
endif()



#-------------------- 打包APK --------------------

set_default(KEYSTORE ${CMAKE_CURRENT_LIST_DIR}/keystore.jks)
set_default(APK_UNSIGNED ${PROJECT_NAME}_unsigned.apk)
set_default(APK_ALIGNED ${PROJECT_NAME}_aligned_unsigned.apk)
set_default(APK ${PROJECT_NAME}.apk)

file(GLOB_RECURSE ALL_RES ${RES}/*) 
foreach(FILENAME IN LISTS RES_FILES)
	set(APK_DEPS ${APK_DEPS} ${FILENAME})
endforeach()

if(EXISTS ${ASSETS})
	set(APK_ASSETS -A ${ASSETS})
endif()
foreach(ABINAME IN LISTS BUILD_ABI)
	set(APK_DEPS ${APK_DEPS} ${CMAKE_BINARY_DIR}/jniLibs/lib/${ABINAME}/lib${PROJECT_NAME}.so)
endforeach()

add_custom_command(OUTPUT ${APK_UNSIGNED} DEPENDS ${APK_DEPS} COMMAND $ENV{ANDROID_BUILD_TOOLS}/aapt p -f -I $ENV{ANDROID_PLATFORM}/android.jar -S ${RES} ${RES_STRING} -M ${MANIFEST}  -F ${APK_UNSIGNED} ${APK_ASSETS} jniLibs)

#-------------------- Zipalign APK --------------------
add_custom_command(OUTPUT ${APK_ALIGNED} DEPENDS ${APK_UNSIGNED} COMMAND $ENV{ANDROID_BUILD_TOOLS}/zipalign -f -v 8 ${APK_UNSIGNED} ${APK_ALIGNED})

#-------------------- Sign APK --------------------
add_custom_command(OUTPUT ${APK} DEPENDS ${APK_ALIGNED} ${KEYSTORE} COMMAND $ENV{ANDROID_BUILD_TOOLS}/apksigner sign --ks ${KEYSTORE} --ks-pass pass:${KEYSTORE_PASSWORD} --in ${APK_ALIGNED} --out ${APK})

#-------------------- Main --------------------
add_custom_target(app_build ALL DEPENDS ${APK})

#-------------------- App Install --------------------
add_custom_target(app_install DEPENDS ${APK} COMMAND adb install -r ${APK})

#-------------------- App Start --------------------
add_custom_target(app_start DEPENDS ${APK} COMMAND adb shell am start ${PACKAGE_NAME}/${ACTIVITY_NAME})





